<template>
	<view :style="{ width: `${_width}rpx`, height: `${_height}rpx` }">
		<!-- #ifdef APP-NVUE -->
		<gcanvas v-if="show" :id="canvasId" :ref="canvasId" class="canvas" :style="{ width: `${_width}rpx`, height: `${_height}rpx` }"> </gcanvas>
		<!-- #endif -->
		<!-- #ifdef MP-WEIXIN || MP-ALIPAY || MP-QQ -->
		<canvas type="2d" id="canvasId" canvas-id="canvasId" class="canvas" :style="{ width: `${_width}rpx`, height: `${_height}rpx` }"></canvas>
		<!-- #endif -->
		<!-- #ifndef MP-WEIXIN || MP-ALIPAY || MP-QQ || APP-NVUE -->
		<canvas :id="canvasId" :canvas-id="canvasId" class="canvas" :style="{ width: `${_width}rpx`, height: `${_height}rpx` }"></canvas>
		<!-- #endif -->
	</view>
</template>

<script lang="ts" setup>
/**
 * 条形码
 * @description 这是一个条形码组件，属性多，可以生成非常个性化的组件哦~
 * 如果想知道生成的属性请查看：Baroptions类型属性。
 * 更改任意属性，都将会导致重绘
 */
import { getCurrentInstance, computed, ref, PropType, inject, ComponentInternalInstance, onMounted, nextTick, watch } from 'vue'
import CanvasRenderingContext2D from '../../tool/gcanvas/context-2d/RenderingContext.js'
import { drawBarCode, BarcodeObjType, Baroptions } from './drawing'
import { JsBarcode } from './jsbarcode/JsBarcode.js'
import JsBarcodeOptions from './jsbarcode/options/defaults.js'
// #ifdef APP-NVUE
import { enable, WeexBridge } from '../../tool/gcanvas/index.js'
// #endif
const proxy = getCurrentInstance()?.proxy ?? null

const props = defineProps({
	option: {
		type: Object as PropType<Baroptions>,
		default: () => {
			return JsBarcodeOptions
		}
	},
	width: {
		type: Number,
		default: 600
	},
	height: {
		type: Number,
		default: 240
	}
})
const vnodeCtx = proxy
const canvasId = ref('canvasId')
// #ifndef MP-WEIXIN || MP-ALIPAY || MP-QQ
canvasId.value = 'tm' + uni.$tm.u.getUid(5)
// #endif
let ctx: CanvasRenderingContext2D
let canvas2d: HTMLCanvasElement
let optsCode = computed(() => {
	let ops = { ...JsBarcodeOptions, ...props.option }
	ops.height = uni.upx2px(props.height) - 40
	return ops
})
const _width = computed(() => props.width)
const _height = computed(() => props.height)
const show = ref(false) //安卓上首次要隐藏不然卡。
onMounted(() => {
	nextTick(function () {
		// #ifdef APP-NVUE
		if (uni.getSystemInfoSync().osName == 'android') {
			setTimeout(function () {
				show.value = true
				init().then(() => draw())
			}, 200)
		} else {
			show.value = true
			init().then(() => draw())
		}
		// #endif
		// #ifndef APP-NVUE

		init().then(() => draw())
		// #endif
	})
})
function draw(opts = optsCode.value) {
	let bcode = JsBarcode(ctx, opts.text, opts)
	let BarcodeObj: BarcodeObjType = bcode._encodings[0][0]
	let is2d = canvas2d ? true : false

	drawBarCode(ctx, BarcodeObj.options, BarcodeObj, is2d, uni.upx2px(_width.value))
}
watch(
	() => props.option,
	() => {
		if (!ctx) {
			init().then(() => draw({ ...optsCode.value }))
		} else {
			draw({ ...optsCode.value })
		}
	},
	{ deep: true }
)
function init() {
	return new Promise((res, rej) => {
		// #ifdef APP-NVUE
		setTimeout(async function () {
			ctx = await drawNvue_init()
			res(true)
		}, 100)
		// #endif
		// #ifdef MP-WEIXIN || MP-ALIPAY || MP-QQ
		setTimeout(async function () {
			const { ctx2d, canvas } = await MpWeix_init()
			ctx = ctx2d
			canvas2d = canvas
			res(true)
		}, 100)
		// #endif
		// #ifndef MP-WEIXIN || MP-ALIPAY || MP-QQ || APP-NVUE
		setTimeout(async function () {
			ctx = await appvueH5Other()
			res(true)
		}, 50)
		// #endif
	})
}
//appvue,h5,和其它平台。
function appvueH5Other() {
	return Promise.resolve(uni.createCanvasContext(canvasId.value, vnodeCtx))
}
//支付宝和微信，QQ 支持2d渲染。
function MpWeix_init(): Promise<{
	ctx2d: CanvasRenderingContext2D
	canvas: HTMLCanvasElement
}> {
	return new Promise((resolve, rej) => {
		const query = uni.createSelectorQuery().in(vnodeCtx)

		// #ifdef MP-ALIPAY
		query
			.select('#canvasId')
			.node()
			.exec((res2) => {
				const canvas = res2[0].node
				let ctxvb: UniApp.CanvasContext = canvas.getContext('2d')
				resolve({ ctx2d: ctxvb, canvas: canvas })
			})
		// #endif
		// #ifdef MP-WEIXIN || MP-QQ
		query
			.select('#canvasId')
			.fields({
				node: true,
				size: true,
				context: true
			})
			.exec((res) => {
				// #ifndef MP-QQ
				const canvas = res[0].node
				const ctxvb = canvas.getContext('2d')
				const dpr = uni.getSystemInfoSync().pixelRatio
				canvas.width = res[0].width * dpr
				canvas.height = res[0].height * dpr
				ctxvb.scale(dpr, dpr)
				resolve({ ctx2d: ctxvb, canvas: canvas })
				// #endif
				// #ifdef MP-QQ
				resolve({ ctx2d: res[0].context, canvas: null })
				// #endif
			})
		// #endif
	})
}
function drawNvue_init() {
	/*获取元素引用*/
	var ganvas = vnodeCtx.$refs[canvasId.value]
	/*通过元素引用获取canvas对象*/
	var canvasObj = enable(ganvas, {
		bridge: WeexBridge
	})
	return canvasObj.getContext('2d')
}
function save(): Promise<string> {
	return new Promise((su, fa) => {
		if (!ctx) {
			uni.showToast({ title: '初始化失败', icon: 'none' })
			fa('初始化失败')
			return
		}
		let width = props.width
		let height = props.height
		// #ifdef APP-NVUE
		uni.showLoading({ title: '...' })
		ctx.toTempFilePath(0, 0, width, height, uni.upx2px(width), uni.upx2px(height), 'png', 1, function (res) {
			uni.hideLoading()
			console.log(res.errMsg)
			if (res.errMsg == 'canvasToTempFilePath:ok') {
				su(res.tempFilePath)
			} else {
				fa(res.errMsg)
			}
		})
		// #endif
		// #ifndef APP-NVUE
		uni.canvasToTempFilePath({
			x: 0,
			y: 0,
			width: uni.upx2px(width),
			height: uni.upx2px(height),
			canvasId: canvasId.value,
			canvas: canvas2d,
			success: function (res) {
				// 在H5平台下，tempFilePath 为 base64
				su(res.tempFilePath)
			},
			fail: (res) => {
				fa(res)
			}
		})

		// #endif
	})
}

//保存条码图片。
defineExpose({ save })
</script>

<style></style>
